/*
 *  Copyright 2005 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.common.parsers.html;

import com.blandware.atleap.common.Constants;

import java.io.Reader;
import java.io.Writer;
import java.io.InputStream;
import java.io.IOException;
import java.util.HashMap;


/**
 * An HTML parser that extracts a plain text.
 *
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.2 $ $Date: 2005/08/02 14:53:29 $
 */
class PlainTextParser extends HTMLParser {

    /**
     * Constructs the PlainTextParser.
     *
     * @param reader             the <code>Reader</code> that will supply an HTML to parse
     * @param writer             the <code>Writer</code> that will accept the extracted text
     * @param lookingForEncoding if we want to find out the document encoding
     *                           ourselves (from &lt;meta&gt; tags, for example)
     * @param stream             the <code>RewindableInputStreamWrapper</code> that supplies
     *                           data for <code>reader</code>. It's needed only if
     *                           <code>lookingForEncoding</code> is <code>true</code> to stop remembering
     *                           bytes when it's clear that no encoding will be found.
     */
    public PlainTextParser(Reader reader, Writer writer, boolean lookingForEncoding,
                               InputStream stream) {
        super(reader, writer, lookingForEncoding, stream);
    }

    protected void addText(String text) throws IOException {
        if (!inStyle && !inScript) {
            if (lookingForEncoding) {
                resultedChars.write(text);
            } else {
                output.write(text);
            }
        }
    }

    protected void addSpace() throws IOException {
        if (!inStyle && !inScript) {
            String space = afterTag ? Constants.EOL : " ";
            if (lookingForEncoding) {
                resultedChars.write(space);
            } else {
                output.write(space);
            }
        }
    }

    protected void processTag(String tagName, HashMap attributes,
                              boolean closing) throws IOException {
        checkoutAttribute(attributes, "title");
        if (tagName.equalsIgnoreCase("<script")) {
            inScript = true;
        } else if (tagName.equalsIgnoreCase("</script")) {
            inScript = false;
        } /*else if (tagName.equalsIgnoreCase("<a")) {
            checkoutAttribute(attributes, "title");
        } */else if (tagName.equalsIgnoreCase("<img")) {
            checkoutAttribute(attributes, "alt");
        } else if (tagName.equalsIgnoreCase("<meta")) {
            checkoutNameContentPair(attributes, "keywords");
            checkoutNameContentPair(attributes, "description");
            checkoutNameContentPair(attributes, "copyright");
            checkoutNameContentPair(attributes, "publisher");
            checkoutNameContentPair(attributes, "author");
            if (lookingForEncoding) {
                checkoutEncodingChange(attributes);
            }
        } else if (tagName.equalsIgnoreCase("</head")
                   || tagName.equalsIgnoreCase("<body")) {
            if (!headFinished) {
                // No valid METAs expected more, so the encoding won't change
                lookingForEncoding = false;
                headFinished = true;
                if (initialStream instanceof RewindableInputStreamWrapper) {
                    RewindableInputStreamWrapper stream = (RewindableInputStreamWrapper) initialStream;
                    stream.stopRemembering();
                    output.write(resultedChars.toCharArray());
                    resultedChars = null;
                }
            }
        }
    }

    /**
     * Considers text -- adds it
     *
     * @param text the text ro be considered
     */
    protected void considerText(String text) throws IOException {
        addText(text);
    }

    /**
     * Considers space -- adds it
     *
     * @throws java.io.IOException
     */
    protected void considerSpace() throws IOException {
        addSpace();
    }
}
